package btb.util;

public abstract class AbstractObjectMap extends AbstractObjectList
{
	public static final int MAX_KEY_VAL = 999999999;
	
	protected int[] listMap = null;
	
	public AbstractObjectMap() {}
	
	public AbstractObjectMap(int _capacity)
	{
		super(_capacity);
		this.listMap = new int[this.capacity];
	}
	
	public synchronized void add(Object _object)
	{
		if(this.count == 0)
		{
			this.list = new Object[this.capacity];
			this.listMap = new int[this.capacity];
		}
		
		if(this.count < this.capacity)
		{
			this.list[this.count] = _object;
			this.listMap[this.count] = this.getUniqueKey();
			this.count++;
		}
		else
		{
			this.grow();
			this.add(_object);
		}
	}
	
	public synchronized int add(Object _object, int _key)
	{
		if(this.count == 0)
		{
			this.list = new Object[this.capacity];
			this.listMap = new int[this.capacity];
		}
		
		if(this.count < this.capacity)
		{
			if(this.findKey(_key) <= -1)
			{
				this.list[this.count] = _object;
				this.listMap[this.count] = _key;
				this.count++;
				return _key;
			}
			else
			{
				return this.add(_object, this.getUniqueKey());
			}
		}
		else
		{
			this.grow();
			return this.add(_object, _key);
		}
	}
	
	public synchronized void remove(Object _object)
	{
		int pos = this.find(_object);
		
		if(pos >= 0)
		{
			this.list[pos] = null;
			this.listMap[pos] = -1;
			System.arraycopy(this.list, pos + 1, this.list, pos, this.list.length - pos - 1);
			System.arraycopy(this.listMap, pos + 1, this.listMap, pos, this.listMap.length - pos - 1);
			this.count--;
		}
	}
	
	public synchronized void removeByIndex(int _pos)
	{
		super.removeByIndex(_pos);
		
		if(_pos < this.capacity)
		{
			this.listMap[_pos] = -1;
			System.arraycopy(this.listMap, _pos + 1, this.listMap, _pos, this.listMap.length - _pos - 1);
		}
	}
	
	public synchronized void remove(int _key)
	{
		int pos = this.findKey(_key);
		
		if(pos >= 0)
		{
			this.list[pos] = null;
			this.listMap[pos] = -1;
			System.arraycopy(this.list, pos + 1, this.list, pos, this.list.length - pos - 1);
			System.arraycopy(this.listMap, pos + 1, this.listMap, pos, this.listMap.length - pos - 1);
			this.count--;
		}
	}
	
	protected void grow()
	{
		super.grow();
		
		int[] tmpkeylist = this.getKeyList();
		this.listMap = new int[this.capacity];
		System.arraycopy(tmpkeylist, 0, this.listMap, 0, tmpkeylist.length);
	}
	
	public synchronized int findKey(int _key)
	{
		for(int i = 0; i < this.count; i++)
			if(this.listMap[i] == _key)
				return i;
		return -1;
	}
	
	public synchronized String toString()
	{
		String tmp;
		String str = "";
		
		str += "Count: " + this.count + "\n";
		str += "Capacity: " + this.capacity + "\n";
		
		if( this.count > 0)
		{
			str += "Mapped Objects:\n";
			for(int i = 0; i < this.count; i++)
			{
				str += "[" + i + "]:  " + "Key: " + this.listMap[i] + ", Object: " + (tmp = this.list[i].getClass().getName());
				if(tmp.equals("String"))
					str += "  '" + this.list[i] + "'";
				str += "\n";
			}
		}
		else
		{
			str += "<Map is empty.>";
		}
		
		return str;
	}
	
	public synchronized Object get(int _key) {
		return this.list[this.findKey(_key)];
	}
	
	protected synchronized int getUniqueKey()
	{
		int x;
		
		for(x = 0; x < MAX_KEY_VAL; x++)
			if(this.findKey(x) <= -1)
				break;
		
		if(x < MAX_KEY_VAL)
			return x;
		return -1;
	}
	
	public synchronized int[] getKeyList()
	{
		return this.listMap;
	}
}
